﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Linq;
using Microsoft.Xna.Framework.Graphics;
using System.Globalization;
using Microsoft.Xna.Framework.Content;
using RPGXEngine;

namespace RPGX.Graphics
{
    public class GameText
    {
        #region Properties

        public ContentManager Content
        {
            get { return _content; }
            set { _content = value; }
        }
        private ContentManager _content = null;

        public Dictionary<string, Dictionary<string, string>> Text
        {
            get { return this._text; }
            set { this._text = value; }
        }
        private Dictionary<string, Dictionary<string, string>> _text = new Dictionary<string, Dictionary<string, string>>();

        public Dictionary<string, LanguageInfo> Languages
        {
            get { return _languages; }
            set { _languages = value; }
        }
        private Dictionary<string, LanguageInfo> _languages = new Dictionary<string, LanguageInfo>();

        private LanguageInfo CurrentLanguage
        {
            get
            {
                var name = CultureInfo.CurrentCulture.Name;

                foreach (LanguageInfo li in this.Languages.Values)
                {
                    if (li.CultureCodes.Contains(name))
                        return li;
                }

                if (this.Languages.Count > 0)
                    return this.Languages.Values.ToList()[0];
                else
                    return null;
            }
        }

        public SpriteFont CurrentFont
        {
            get
            {
                // if the culture changes, simply restart the game. I think it is too much
                // to be constantly checking to see if the culture changes mid-game, as I highly
                // doubt this will...
                if (this._currentFont == null)
                {
                    this._currentFont = this.Content.Load<SpriteFont>(String.Format(".\\HUD\\Fonts\\{0}", this.CurrentLanguage.SpriteFileName));
                }

                return this._currentFont;
            }
        }
        private SpriteFont _currentFont = null;

        #endregion

        #region Public Methods

        public GameText(ContentManager content)
        {
            this.Content = content;
        }

        public bool Load(string directory)
        {
            if (!this.UnLoad())
                return false;

            this.LoadLanguages(directory);

            var files = Directory.GetFiles(directory, "*.text");

            foreach (var file in files)
            {
                this.ProcessTextFile(file);
            }

            return true;
        }

        public bool UnLoad()
        {
            this.Text.Clear();

            this.Languages.Clear();

            return true;
        }

        public string GetText(string key)
        {
            var l = this.Text[this.CurrentLanguage.Name];

            string k = key.ToLower();

            if (l.ContainsKey(k))
                return l[k];
            else
                return String.Format("Failed to find key '{0}' for language '{1}'.",
                    key, this.CurrentLanguage.Name);
        }

        #endregion

        #region Private Methods

        private void LoadLanguages(string directory)
        {
            XDocument doc = XDocument.Load(String.Format("{0}\\languages.lng", directory));

            foreach (var language in doc.Element("languages").Elements("language"))
            {
                LanguageInfo info = new LanguageInfo();

                info.Name = language.Attribute("name").Value;
                info.SpriteFileName = language.Attribute("spritefontfile").Value;

                foreach (var culturecode in language.Elements("culturecode"))
                {
                    info.CultureCodes.Add(culturecode.Value);
                }

                this.Languages.Add(info.Name.ToLower(), info);
            }
        }

        private void ProcessTextFile(string fileName)
        {
            try
            {
                XDocument doc = XDocument.Load(fileName);

                foreach(var language in doc.Element("text").Elements("language"))
                {
                    var name = language.Attribute("name").Value;
                    if (this.Languages.ContainsKey(name))
                    {
                        if (!this.Text.ContainsKey(name))
                            this.Text.Add(name, new Dictionary<string, string>());

                        foreach (var item in language.Elements("item"))
                        {
                            var key = item.Attribute("key");

                            if (key != null && !String.IsNullOrEmpty(key.Value))
                            {
                                string index = key.Value.ToLower().Trim();

                                if (!this.Text.ContainsKey(index))
                                {
                                    this.Text[name].Add(index, item.Value);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                // TODO log an error
            }
        }

        #endregion
    }
}
